use std::path::PathBuf;

use re_build_tools::write_file_if_necessary;

fn should_run() -> bool {
    #![allow(clippy::match_same_arms)]
    use re_build_tools::Environment;

    match Environment::detect() {
        // The code (which is committed) should hopefully already be up-to-date.
        Environment::PublishingCrates => false,

        // No need to run this on CI (which means setting up `protoc` etc)
        // since the code is committed anyway.
        Environment::RerunCI | Environment::CondaBuild => false,

        // Sure - let's keep it up-to-date.
        Environment::DeveloperInWorkspace => true,

        // Definitely not
        Environment::UsedAsDependency => false,
    }
}

fn main() -> Result<(), std::io::Error> {
    if !should_run() {
        return Ok(());
    }

    match protoc_prebuilt::init("22.0") {
        Ok((protoc_bin, _)) => {
            std::env::set_var("PROTOC", protoc_bin);
        }
        Err(err) => {
            eprintln!("Failed to install protoc: {err} - falling back to system 'protoc'");
        }
    }

    prost_build::compile_protos(
        &[
            "proto/a_r_capture_metadata.proto",
            "proto/annotation_data.proto",
            "proto/object.proto",
        ],
        &["proto"],
    )?;

    let out_dir = re_build_tools::get_and_track_env_var("OUT_DIR").unwrap();
    let src_path = PathBuf::from(out_dir).join("objectron.proto.rs");
    let dst_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/objectron.rs");

    // `include!()` will break LSP & GitHub navigation, so create an actual source file to make the
    // UX reasonable.

    let bytes = [
        b"// This file was autogenerated by `build.rs`. Do not edit.\n\n".to_vec(),
        b"#![allow(clippy::all, clippy::doc_markdown)]\n".to_vec(),
        std::fs::read(src_path)?,
    ]
    .into_iter()
    .flatten()
    .collect::<Vec<_>>();

    // `cargo` has an implicit `rerun-if-changed=src/**` clause, which will act against us in this
    // instance.
    // Make sure to _not_ rewrite identical data, so as to avoid being stuck in an infinite build
    // loop when using tools like e.g. `bacon` that watch the filesystem for any changes to the
    // project's files.
    write_file_if_necessary(dst_path, &bytes)
}
